extension IterableNullEx<E> on Iterable<E>? {
  bool get isNullOrEmpty => this == null || this!.isEmpty;

  bool get isNotNullOrEmpty => this != null && this!.isNotEmpty;
}

extension IterableEx<E> on Iterable<E> {
  /// 查找满足条件的第一个元素
  E? findFirst(bool Function(E element) test) {
    if (isEmpty) {
      return null;
    }

    for (var value in this) {
      if (test.call(value)) {
        return value;
      }
    }
    return null;
  }

  /// 查找满足条件的最后元素
  E? findLast(bool Function(E element) test) {
    if (isEmpty) {
      return null;
    }

    E? result;
    for (var value in this) {
      if (test.call(value)) {
        result = value;
      }
    }
    return result;
  }

  /// 将列表拼接成字符串
  ///
  /// 默认[getValue]返回的字符如果是空串则不进行拼接，如果需要拼接，[valueEmptyAppend]置为true即可
  String? appendToStr(String? Function(E value) getValue,
      {String delimiter = ",", bool valueEmptyAppend = false}) {
    var data = this;
    if (data.isEmpty) {
      return null;
    }

    String? strs;
    for (var value in data) {
      var str = getValue.call(value);
      if (str == null) {
        continue;
      }

      if (!valueEmptyAppend && str.isEmpty) {
        continue;
      }

      if (strs == null) {
        strs = str;
      } else {
        strs += "$delimiter$str";
      }
    }

    return strs;
  }

  /// 将列表拼接成多个字符串
  ///
  /// [delimiters]不传默认分隔符为","，如果传了此值，其长度需要与[getValues]保持一致。
  /// 默认[getValues]返回的字符如果是空串则不进行拼接，如果需要拼接，[valueEmptyAppend]置为true即可
  List<String?> appendToStrArray(List<String? Function(E value)> getValues,
      {List<String>? delimiters, bool valueEmptyAppend = false}) {
    var list = <String?>[];
    for (var _ in getValues) {
      list.add(null);
    }

    var data = this;
    if (data.isEmpty || getValues.isEmpty) {
      return list;
    }

    for (var value in data) {
      for (int i = 0; i < getValues.length; i++) {
        var getValue = getValues[i];
        var str = getValue.call(value);
        if (str == null) {
          continue;
        }

        if (!valueEmptyAppend && str.isEmpty) {
          continue;
        }

        var strs = list[i];
        var delimiter = delimiters.isNullOrEmpty ? "," : delimiters![i];
        if (strs == null) {
          strs = str;
        } else {
          strs += "$delimiter$str";
        }
        list[i] = strs;
      }
    }

    return list;
  }

  /// 当前列表项在[other]列表有匹配的对象时执行map操作。
  /// [equals]用来匹配两个列表项是否相等，如果相等则回调[map]。
  ///
  /// 此扩展主要用于使用[other]数据更新当前列表数据
  void mapInOtherList<O>(Iterable<O>? other, bool Function(E e, O o) equals,
      Function(E e, O o) map) {
    if (isEmpty) {
      return;
    }

    if (other == null || other.isEmpty) {
      return;
    }

    for (var value in this) {
      for (var value2 in other) {
        if (equals(value, value2)) {
          map(value, value2);
          break;
        }
      }
    }
  }
}

extension ListEx<E> on List<E> {
  /// 查找满足条件的元素然后转化该元素
  List<T> whereAndMap<T>(
      bool Function(E element) test, T Function(E e) toElement) {
    List<T> result = [];
    if (isEmpty) {
      return result;
    }

    for (var value in this) {
      if (test.call(value)) {
        result.add(toElement(value));
      }
    }

    return result;
  }

  /// 将列表两个下标的数据进行位置调换
  swap(int leftIndex, int rightIndex) {
    var left = this[leftIndex];
    var right = this[rightIndex];
    removeAt(leftIndex);
    insert(leftIndex, right);
    removeAt(rightIndex);
    insert(rightIndex, left);
  }
}
